home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Abalone 1.4.2 / src / Draw3D.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-21  |  10.0 KB  |  480 lines  |  [TEXT/MPS ]

  1. #define DRAW_3D_C
  2. #include "Draw3D.h"
  3. #undef DRAW_3D_C
  4.  
  5.  
  6. #if defined(__MWERKS__)
  7. #pragma segment __%Main
  8. #else
  9. #pragma segment Main
  10. #endif
  11.  
  12.  
  13. #define WORLDSIZE        54
  14.  
  15. static GWorldPtr        myRoundWorld[kPlayers+1] = { 0L, 0L, 0L, 0L };
  16. static Rect                offRect = { 0, 0, WORLDSIZE, WORLDSIZE };
  17. static Rect                resRect = { 0, 0, 0, 0};
  18. static PaletteHandle    pH = 0L;
  19. static Boolean            invalidated = false;
  20.  
  21.  
  22.  
  23. void
  24. DrawBallColor3D (Field field, char color)
  25. {
  26.     RgnHandle        ballRgn;
  27.     Rect             ballRect;
  28.     RGBColor        edgeColor;
  29.         
  30. //    Assert (gSet.Balls3D, INTERNAL_ERROR);
  31. //    Assert (ColorQDAvailable(), INTERNAL_ERROR);
  32.     
  33.     if (! myRoundWorld[color])
  34.         Init3D();
  35.  
  36. //    Draw the ball using CopyBits to get it from an offscreen world.
  37.  
  38.      ballRect = FieldToBallRect (field);
  39.     ballRgn = NewRgn();
  40.     OpenRgn();
  41.     ForeColor (blackColor);
  42.     BackColor (whiteColor);
  43.     FrameOval (& ballRect);
  44.     CloseRgn (ballRgn);
  45.  
  46.     ForeColor (blackColor);
  47.     BackColor (whiteColor);
  48.     CopyBits (    (BitMapPtr) *myRoundWorld[color]->portPixMap,
  49.                 &(*gAbaloneWindow).portBits,
  50.                 &offRect,
  51.                 & ballRect,
  52.                 ditherCopy,
  53.                 ballRgn
  54.             );
  55.     
  56.     edgeColor.red = gSet.Color[color].red / 2;
  57.     edgeColor.green = gSet.Color[color].green / 2;
  58.     edgeColor.blue = gSet.Color[color].blue / 2;
  59.     RGBForeColor (& edgeColor);
  60.     FrameOval (& ballRect);
  61.     ForeColor (blackColor);
  62.     RGBBackColor (& gSet.Color[0]);
  63.     
  64.     DisposeRgn (ballRgn);
  65. }
  66.  
  67.  
  68. static short    savedWidth = 0;
  69. static short    savedHeight = 0;
  70.  
  71. #define PushSizes    { savedWidth = gSet.FieldWidth; savedHeight = gSet.FieldHeight; }
  72. #define PopSizes    { gSet.FieldWidth = savedWidth; gSet.FieldHeight = savedHeight;    }
  73.  
  74. void
  75. DrawFieldColor3D (Field field)
  76. {
  77.     Rect             fieldRect;
  78.     Rect            pictRect;
  79.     
  80.     if (! myRoundWorld[0])
  81.         Init3D();
  82.         
  83.     if (EmptyRect (& resRect))
  84.         return;
  85.  
  86.      fieldRect = FieldToRect (field);
  87.     pictRect = fieldRect;
  88.  
  89.     MapRect (& pictRect, & gAbaloneWindow->portRect, & resRect /* & myRoundWorld[0]->portRect */);
  90.     ForeColor (blackColor);
  91.     BackColor (whiteColor);
  92.     CopyBits (    *( (BitMap **) GetGWorldPixMap (myRoundWorld[0])),
  93.                 &(*gAbaloneWindow).portBits,
  94.                 &pictRect,
  95.                 &fieldRect,
  96.                 ditherCopy,
  97.                 0L
  98.             );
  99.     ForeColor (blackColor);
  100.     RGBBackColor (& gSet.Color[0]);
  101. }
  102.  
  103.  
  104.  
  105. void
  106. Init3D (void)
  107. {
  108.     if (! pH && ColorQDAvailable() && gSet.Balls3D)
  109.         SetUpPalette();
  110.     
  111.     if (ColorQDAvailable() && gSet.Balls3D)
  112.         SetUpGWorlds();
  113. }
  114.  
  115.  
  116.  
  117. void
  118. Inval3D (void)
  119. {
  120.     invalidated = true;
  121. }
  122.  
  123.  
  124.  
  125. void
  126. Update3D (void)
  127. {
  128.     if (! invalidated)
  129.         return;
  130.  
  131.     UpdatePalette();
  132.     UpdateGWorlds();
  133.     invalidated = false;
  134. }
  135.  
  136.  
  137.  
  138. void
  139. UpdatePalette (void)
  140. {
  141.     if (pH)
  142.     {
  143.         DisposePalette (pH);
  144.         pH = 0L;
  145.     }
  146.     if (gSet.Balls3D && ColorQDAvailable())
  147.         SetUpPalette();
  148. }
  149.  
  150.  
  151.  
  152. void
  153. UpdateGWorlds (void)
  154. {
  155.     short            world;
  156.     
  157.     for (world = 0; world <= kPlayers; world++)
  158.     {
  159.         if (myRoundWorld[world])
  160.         {
  161.             DisposeGWorld (myRoundWorld[world]);
  162.             myRoundWorld[world] = 0L;
  163.         }
  164.     }
  165.     if (gSet.Balls3D && ColorQDAvailable())
  166.         SetUpGWorlds();
  167. }
  168.  
  169.  
  170.  
  171. void
  172. SetUpPalette (void)
  173. {
  174.     #define            pmDefaultOptions     pmTolerant + (pixSize == 8 ? 0 : pmExplicit), 0
  175.     unsigned short     dR, dG, dB;
  176.     RGBColor        ovalColor;
  177.     short            world;
  178.     short            i;
  179.     short            pixSize = PixelSize();
  180.     short             colorsPerPlayer;
  181.     short            paletteSize;
  182.     CTabHandle        tmpTable;
  183.     
  184.     if (! gSet.Balls3D)        //    No need for a palette (no 3D effects).
  185.         return;
  186.         
  187.     if (pixSize > 8)        //    No need for a palette (direct pixels).
  188.         return;
  189.         
  190.     if (pH)
  191.     {
  192.         DisposePalette (pH);
  193.         pH = 0L;
  194.     }
  195.     
  196.     switch (pixSize)
  197.     {
  198.         case 1:
  199.         case 2:
  200.             colorsPerPlayer = 0;
  201.         break;
  202.         case 8:
  203.             colorsPerPlayer = WORLDSIZE >> 1;
  204.         break;
  205.         default:
  206.             colorsPerPlayer = ((1 << pixSize) - 4) / gSet.Players;
  207.         break;
  208.     }
  209.     paletteSize = 2 + gSet.Players * colorsPerPlayer;
  210.  
  211.     if ((pH = NewPalette (paletteSize, 0L, pmCourteous, 0)) == NULL)
  212.     {
  213.         Warning (SHORT_ON_MEMORY);
  214.         gSet.Balls3D = false;
  215.         return;
  216.     }
  217.     
  218.     if ((tmpTable = GetCTable (pixSize)) == 0)            //    try to get default color table
  219.     {
  220.     //    Could not get the default color table; probably a direct device.
  221.     //    Can't do anything useful without a color table.
  222.  
  223.         return;
  224.     }
  225.  
  226. //    Initialise the palette with the default color table
  227.  
  228. //    CTab2Palette (tmpTable, pH, pmTolerant, 0);
  229.     DisposCTable (tmpTable), tmpTable = 0;
  230.         
  231. //    Put white in first entry. (explicit).
  232.  
  233.     ovalColor.red = ovalColor.green = ovalColor.blue = 0xFFFF;
  234.     SetEntryColor (pH, 0, & ovalColor);
  235.     SetEntryUsage (pH, 0, pmDefaultOptions);
  236.     
  237. //    add gray & chosen background color & black (for 2-bit setting).
  238.  
  239.     ovalColor.red = ovalColor.green = ovalColor.blue = 0x7FFF;
  240.     SetEntryColor (pH, 1, & ovalColor);
  241.     SetEntryUsage (pH, 1, pmDefaultOptions);
  242.  
  243.     ovalColor.red = gSet.Color[0].red;
  244.     ovalColor.green = gSet.Color[0].green;
  245.     ovalColor.blue = gSet.Color[0].blue;
  246.     
  247.     SetEntryColor (pH, 2, & ovalColor);
  248.     SetEntryUsage (pH, 2, pmDefaultOptions);
  249.     
  250.     ovalColor.red = ovalColor.green = ovalColor.blue = 0x0;
  251.     SetEntryColor (pH, 3, & ovalColor);
  252.     SetEntryUsage (pH, 3, pmDefaultOptions);
  253.     
  254.  
  255. //    Consider the first four entries filled.
  256. //    Twelve colors remain for a sixteen-color palette, 252 for a 256-color palette
  257. //    (black is moved to the last position, entry 3 is reused)
  258.  
  259.     if (pixSize == 4 || pixSize == 8) for (world = 1; world <= gSet.Players; world++)
  260.     {                
  261.         
  262.         ovalColor.red = gSet.Color[world].red / 2;
  263.         ovalColor.green = gSet.Color[world].green / 2;
  264.         ovalColor.blue = gSet.Color[world].blue / 2;
  265.         
  266.     //    Add as much relevant colors for each ball as is possible or useful.
  267.             
  268.         for    (    dR = dG = dB = (pixSize == 8 ? 2475 : (0x8000 / colorsPerPlayer)), i = 0;
  269.                 i < colorsPerPlayer - 1;
  270.                 i++)
  271.         {
  272.             short index = colorsPerPlayer * (world - 1) + i + 3;
  273.             
  274.             Assert (index  <paletteSize, INTERNAL_ERROR);
  275.             
  276.             SetEntryColor (pH, index, & ovalColor);
  277.             SetEntryUsage (pH, index, pmDefaultOptions);
  278.             
  279.             ovalColor.red +=   dR;
  280.             ovalColor.green += dG;
  281.             ovalColor.blue +=  dB;
  282.             
  283.         //    Decrease the increase exponentially
  284.             if (pixSize == 8)
  285.             {
  286.             //    Decrease the increase exponentially
  287.         
  288.                 dR -= dR >> 4;
  289.                 dG -= dG >> 4;
  290.                 dB -= dB >> 4;
  291.                 
  292.             }
  293.         }
  294.         
  295.     //    Put black at last position
  296.     
  297.         ovalColor.red = ovalColor.green = ovalColor.blue = 0x0;
  298.         SetEntryColor (pH, paletteSize - 1, & ovalColor);
  299.         SetEntryUsage (pH, paletteSize - 1, pmDefaultOptions);
  300.     }
  301.     SetPalette (gAbaloneWindow, pH, true);
  302.     ActivatePalette (gAbaloneWindow);
  303. }
  304.  
  305.  
  306.  
  307. void
  308. SetUpGWorlds (void)
  309. {
  310.     unsigned short     dR, dG, dB;
  311.     GDHandle        oldDevice;
  312.     CGrafPtr        oldPort;
  313.     Rect            ballRect;
  314.     RGBColor        ovalColor;
  315.     short            world;
  316.             
  317.     Assert (! myRoundWorld[0] || ! myRoundWorld[1], INTERNAL_ERROR);    
  318.     
  319.     GetGWorld (&oldPort, &oldDevice);
  320.     
  321.     if (! myRoundWorld[0])    //    Background
  322.     {
  323.         PicHandle pict = (PicHandle) GetResource ('PICT', gSet.BackgroundPictID);
  324.         if (pict != 0)
  325.         {
  326.         //    save picture boundsrect in global variable.
  327.         
  328.             resRect = (*pict)->picFrame;
  329.                 
  330.             MoveHHi ((Handle) pict);
  331.             HLock ((Handle) pict);
  332.             
  333.         //    Create offscreen GWorld for the background.
  334.             if    (    NewGWorld (    &myRoundWorld[0],
  335.                                 16, //8,
  336.                                 & (*pict)->picFrame,
  337.                                 nil,
  338.                                 nil,
  339.                                 0)
  340.                 != noErr)
  341.             {
  342.                 gSet.Balls3D = false;
  343.                 Warning (GRAPHIC_3D_TURNED_OFF);
  344.                 return;
  345.             }
  346.             SetGWorld (myRoundWorld[0], nil);
  347.             EraseRect (& (*pict)->picFrame);
  348.             DrawPicture (pict, & (*pict)->picFrame);
  349.             HUnlock ((Handle) pict);
  350.             ReleaseResource ((Handle) pict);
  351.         }
  352.     }
  353.     
  354.     if (gSet.Balls3D && ! myRoundWorld[1]) for (world = 1; world <= kPlayers; world++)
  355.     {            
  356.     //    Create offscreen GWorld for this players ball.
  357.     
  358.         Assert (! NewGWorld (    &myRoundWorld[world],
  359.                                 16,
  360.                                 &offRect,
  361.                                 nil,
  362.                                 nil,
  363.                                 0),
  364.                 INSUFFICIENT_MEMORY);
  365.         
  366.         SetGWorld (myRoundWorld[world], nil);
  367.                 
  368.         
  369.     //    Draw the ball to the offscreen pixmap.
  370.         
  371.         ForeColor (blackColor);
  372.         PaintRect (& offRect);
  373.     
  374.             
  375.     //    dR = dG = dB = 2443;    // WORLDSIZE = 55, >> 4
  376.         dR = dG = dB = 2475;    // WORLDSIZE = 54, >> 4
  377.     
  378.     //    dR = dG = dB = 2594;    // value determined empirically for WORLDSIZE = 50, dX -= dX >> 4
  379.     //    dR = dG = dB = 4238;    // value determined empirically for WORLDSIZE = 50, dX -= dX >> 3
  380.         
  381.     //    Start a bit darker at the edges, end a bit lighter in the center.
  382.     
  383.         ovalColor.red = gSet.Color[world].red / 2;
  384.         ovalColor.green = gSet.Color[world].green / 2;
  385.         ovalColor.blue = gSet.Color[world].blue / 2;
  386.         
  387.         RGBForeColor (& ovalColor);
  388.         PaintRect (& ballRect);
  389.             
  390.         for (ballRect = offRect; ! EmptyRect (& ballRect); InsetRect (& ballRect, 1, 1))                
  391.         {
  392.             if ((ballRect.bottom - ballRect.top) % 8 < 2)
  393.                 OffsetRect (& ballRect, 0, 1);
  394.                 
  395.             RGBForeColor (& ovalColor);
  396.             PaintOval (& ballRect);
  397.             
  398.         //    Gradually increase going inwards    
  399.         
  400.             ovalColor.red +=   dR;
  401.             ovalColor.green += dG;
  402.             ovalColor.blue +=  dB;
  403.             
  404.         //    Decrease the increase exponentially
  405.         
  406.             dR -= dR >> 4;
  407.             dG -= dG >> 4;
  408.             dB -= dB >> 4;
  409.             
  410.         //    Total increase should be about 32767
  411.         }
  412.  
  413.         PenMode (addMax);
  414.  
  415.         dR = dG = dB = 2475;    // WORLDSIZE = 54, >> 4
  416.  
  417.         ovalColor.red = gSet.Color[world].red / 2;
  418.         ovalColor.green = gSet.Color[world].green / 2;
  419.         ovalColor.blue = gSet.Color[world].blue / 2;
  420.         
  421.         RGBForeColor (& ovalColor);
  422.         PaintRect (& ballRect);
  423.         for (ballRect = offRect; ! EmptyRect (& ballRect); InsetRect (& ballRect, 1, 1))
  424.         {
  425.             if ((ballRect.bottom - ballRect.top) % 4 < 2)
  426.                 OffsetRect (& ballRect, -1, 0);
  427.                 
  428.             if ((ballRect.bottom - ballRect.top) % 6 < 2)
  429.                 OffsetRect (& ballRect, 0, 1);
  430.                 
  431.             RGBForeColor (& ovalColor);
  432.             PaintOval (& ballRect);
  433.             
  434.         //    Gradually increase going inwards    
  435.         
  436.             ovalColor.red +=   dR;
  437.             ovalColor.green += dG;
  438.             ovalColor.blue +=  dB;
  439.             
  440.         //    Decrease the increase exponentially
  441.         
  442.             dR -= dR >> 4;
  443.             dG -= dG >> 4;
  444.             dB -= dB >> 4;
  445.             
  446.         //    Total increase should be about 32767
  447.         }
  448.  
  449.         PenMode (srcCopy);
  450.  
  451.         ForeColor (blackColor);
  452.     }
  453.     SetGWorld (oldPort, oldDevice);
  454. }
  455.  
  456.  
  457.  
  458. void
  459. DrawBackground (WindowPtr abaloneWindow)
  460. {
  461.     if (! myRoundWorld[0])
  462.         Init3D();
  463.         
  464.     if (! gSet.Balls3D)    //    Failure to initialise offscreen world resets flag
  465.         return;
  466.     
  467.     ForeColor (blackColor);
  468.     BackColor (whiteColor);
  469.     
  470.     CopyBits (    (BitMapPtr) *myRoundWorld[0]->portPixMap,//*( (BitMap **) GetGWorldPixMap (myRoundWorld[0])),
  471.                 &(*abaloneWindow).portBits,
  472.                 & resRect,
  473.                 & abaloneWindow->portRect,
  474.                 ditherCopy,
  475.                 abaloneWindow->visRgn
  476.             );
  477.  
  478.     RGBBackColor (& gSet.Color[0]);
  479. }
  480.